{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CIFAR10 Image Classifier Explanations\n",
    "\n",
    "\n",
    "We will use a Tensorflow classifier built on [CIFAR10 image dataset](https://www.cs.toronto.edu/~kriz/cifar.html) which is a 10 class image dataset.\n",
    "\n",
    "The Kfserving resource describes:\n",
    "   * A pretrained tensorflow model stored on a Google bucket\n",
    "   * Am AnchorImage [Seldon Alibi](https://github.com/SeldonIO/alibi) Explainer. See the [Alibi Docs](https://docs.seldon.io/projects/alibi/en/stable/) for further details.\n",
    "   \n",
    "To download and get the pretrained image classifier locally you can run the following code:\n",
    "\n",
    "```python\n",
    "url = \"https://storage.googleapis.com/seldon-models/alibi-detect/classifier/\"\n",
    "path_model = os.path.join(url, \"cifar10\", \"resnet32\", \"model.h5\")\n",
    "save_path = tf.keras.utils.get_file(\"resnet32\", path_model)\n",
    "model = tf.keras.models.load_model(save_path)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pygmentize cifar10.yaml"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!kubectl apply -f cifar10.yaml -n default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!kubectl wait --for condition=ready --timeout=600s pods --all -n default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "CLUSTER_IPS = !(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n",
    "CLUSTER_IP = CLUSTER_IPS[0]\n",
    "print(CLUSTER_IP)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SERVICE_HOSTNAMES = !(kubectl get inferenceservice cifar10 -n default -o jsonpath='{.status.url}' | cut -d \"/\" -f 3)\n",
    "SERVICE_HOSTNAME = SERVICE_HOSTNAMES[0]\n",
    "print(SERVICE_HOSTNAME)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "\n",
    "sys.path.append(\"../\")\n",
    "from alibi_helper import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import tensorflow as tf\n",
    "\n",
    "train, test = tf.keras.datasets.cifar10.load_data()\n",
    "X_train, y_train = train\n",
    "X_test, y_test = test\n",
    "\n",
    "X_train = X_train.astype(\"float32\") / 255\n",
    "X_test = X_test.astype(\"float32\") / 255\n",
    "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)\n",
    "class_names = [\n",
    "    \"airplane\",\n",
    "    \"automobile\",\n",
    "    \"bird\",\n",
    "    \"cat\",\n",
    "    \"deer\",\n",
    "    \"dog\",\n",
    "    \"frog\",\n",
    "    \"horse\",\n",
    "    \"ship\",\n",
    "    \"truck\",\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "from subprocess import PIPE, Popen, run\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "idx = 12\n",
    "test_example = X_test[idx : idx + 1].tolist()\n",
    "payload = '{\"instances\":' + f\"{test_example}\" + \" }\"\n",
    "cmd = f\"\"\"curl -s -d '{payload}' \\\n",
    "   http://{CLUSTER_IP}/v1/models/cifar10:predict \\\n",
    "   -H \"Host: {SERVICE_HOSTNAME}\" \\\n",
    "   -H \"Content-Type: application/json\"\n",
    "\"\"\"\n",
    "ret = Popen(cmd, shell=True, stdout=PIPE)\n",
    "raw = ret.stdout.read().decode(\"utf-8\")\n",
    "res = json.loads(raw)\n",
    "print(res)\n",
    "arr = np.array(res[\"predictions\"])\n",
    "X = X_test[idx].reshape(1, 32, 32, 3)\n",
    "plt.imshow(X.reshape(32, 32, 3))\n",
    "plt.axis(\"off\")\n",
    "plt.show()\n",
    "print(\"class:\", class_names[y_test[idx][0]])\n",
    "print(\"prediction:\", class_names[arr[0].argmax()])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_example = X_test[idx : idx + 1].tolist()\n",
    "payload = '{\"instances\":' + f\"{test_example}\" + \" }\"\n",
    "cmd = f\"\"\"curl -s -d '{payload}' \\\n",
    "   http://{CLUSTER_IP}/v1/models/cifar10:explain \\\n",
    "   -H \"Host: {SERVICE_HOSTNAME}\" \\\n",
    "   -H \"Content-Type: application/json\"\n",
    "\"\"\"\n",
    "ret = Popen(cmd, shell=True, stdout=PIPE)\n",
    "raw = ret.stdout.read().decode(\"utf-8\")\n",
    "explanation = json.loads(raw)\n",
    "arr = np.array(explanation[\"data\"][\"anchor\"])\n",
    "plt.imshow(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Teardown"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!kubectl delete -f cifar10.yaml -n default"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
